package utility;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;

import javax.imageio.ImageIO;

import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.Imaging;

public class PhotoClassesCreator {
	private String sourcePath = System.getenv("HOME") + File.separator
			+ "workload" + File.separator + "input";
	private static String destinationPath = System.getenv("HOME")
			+ File.separator + "workload" + File.separator + "output";

	public static File size_0_100 = new File(destinationPath + File.separator
			+ "size_0_100");
	public static File size_101_200 = new File(destinationPath + File.separator
			+ "size_101_200");
	public static File size_201_300 = new File(destinationPath + File.separator
			+ "size_201_300");
	public static File size_301_400 = new File(destinationPath + File.separator
			+ "size_301_400");

	private ArrayList<String> imageType;

	public PhotoClassesCreator() {
		createDestinationDirectory();
		this.imageType = new ArrayList<String>();
		this.imageType.add("jpg");
		// this.imageType.add("png");
		// this.imageType.add("gif");
		// this.imageType.add("bmp");

	}

	public void move(File source, File destination) throws IOException {
		InputStream inStream = null;
		OutputStream outStream = null;

		inStream = new FileInputStream(source);
		outStream = new FileOutputStream(destination);

		byte[] buffer = new byte[1024];

		int length;
		// copy the file content in bytes
		while ((length = inStream.read(buffer)) > 0) {

			outStream.write(buffer, 0, length);

		}

		inStream.close();
		outStream.close();
		source.delete();
		System.out.println("File is copied successful!");
	}

	private void createDestinationDirectory() {
		File destinationParentDir = new File(destinationPath);
		if (!destinationParentDir.isDirectory())
			destinationParentDir.mkdir();

		size_0_100 = new File(destinationParentDir.toString() + File.separator
				+ "size_0_100");
		if (!size_0_100.isDirectory())
			size_0_100.mkdir();

		size_101_200 = new File(destinationParentDir.toString()
				+ File.separator + "size_101_200");
		if (!size_101_200.isDirectory())
			size_101_200.mkdir();

		size_201_300 = new File(destinationParentDir.toString()
				+ File.separator + "size_201_300");
		if (!size_201_300.isDirectory())
			size_201_300.mkdir();

		size_301_400 = new File(destinationParentDir.toString()
				+ File.separator + "size_301_400");
		if (!size_301_400.isDirectory())
			size_301_400.mkdir();

	}

	private void processFiles() {
		File file = new File(sourcePath);
		if (file.isDirectory()) {
			File[] filesInDir = file.listFiles();
			Arrays.sort(filesInDir);
			for (File f : filesInDir) {
				if (f.isFile()) {
					try {
						if (imageType.contains(f.getName()
								.substring(f.getName().lastIndexOf('.') + 1)
								.toLowerCase())) {
							System.out.println(f.getName());
							double l = f.length() / 1024;

							if (l > 0 && l <= 100) {
								move(f, new File(destinationPath
										+ File.separator + "size_0_100"
										+ File.separator + f.getName()));
							} else if (l > 100 && l <= 200) {
								move(f, new File(destinationPath
										+ File.separator + "size_101_200"
										+ File.separator + f.getName()));
							} else if (l > 200 && l <= 300) {
								move(f, new File(destinationPath
										+ File.separator + "size_201_300"
										+ File.separator + f.getName()));
							} else if (l > 300 && l <= 400) {
								move(f, new File(destinationPath
										+ File.separator + "size_301_400"
										+ File.separator + f.getName()));
							} else {
								f.delete();
							}
						} else {
							f.delete();
						}
					} catch (StringIndexOutOfBoundsException e) {
						continue;
					} catch (IOException e) {
						System.err.println("e - " + e.fillInStackTrace());
					}
				}
			}
		}
	}

	private void preAnalysis(File fileClassDir) {
		File[] fileList = list(fileClassDir);
		ArrayList<Double> data = new ArrayList<Double>();
		
		for (File file : fileList) {
			// Delete unreadable file
			try {
				BufferedImage cat = Imaging.getBufferedImage(file);
				if (cat == null)
					file.delete();
			} catch (ImageReadException e) {
				file.delete();
				continue;
			} catch (IOException e) {
				if (file != null) {
					file.delete();
					continue;
				}
			}
			
			
			
			double filesize = file.length();
			double filesizeInKB = filesize / 1024;
			data.add(filesizeInKB);
		}
		Statistics stat = new Statistics(data);
		System.out.println("==PreAnalysis of class: " + fileClassDir.getName());
		System.out.println("Mean: " + stat.getMean());
		System.out.println("Var.: " + stat.getVariance());
		System.out.println("StdDev.: " + stat.getStdDev());
		//System.out.println("Median.: " + stat.median());
	}

	public class Statistics {
		private ArrayList<Double> data;
		double size;

		public Statistics(ArrayList<Double> data) {
			this.data = data;
			size = data.size();
		}
		
		public void add(double d){
			data.add(d);
		}

		double getMean() {
			double sum = 0.0;
			for (double a : data)
				sum += a;
			return sum / size;
		}

		double getVariance() {
			double mean = getMean();
			double temp = 0;
			for (double a : data)
				temp += (mean - a) * (mean - a);
			return temp / size;
		}

		double getStdDev() {
			return Math.sqrt(getVariance());
		}

		public double median() {
			double[] b = new double[data.size()];
			System.arraycopy(data, 0, b, 0, b.length);
			Arrays.sort(b);

			if (data.size() % 2 == 0) {
				return (b[(b.length / 2) - 1] + b[b.length / 2]) / 2.0;
			} else {
				return b[b.length / 2];
			}
		}
	}

	private File[] list(File dir) {
		return dir.listFiles(new FilenameFilter() {
			public boolean accept(File arg0, String name) {
				return (imageType.contains(name.substring(
						name.lastIndexOf('.') + 1).toLowerCase()));
			}
		});
	}

	public static void main(String[] ags) {
		PhotoClassesCreator pp = new PhotoClassesCreator();
		//pp.processFiles();
		pp.preAnalysis(size_0_100);
		pp.preAnalysis(size_101_200);
		pp.preAnalysis(size_201_300);
		pp.preAnalysis(size_301_400);

	}
}
